home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1992 by Michael Davidson.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that copyright notice and this permission
- * notice appear in supporting documentation.
- *
- * This software is provided "as is" without express or implied warranty.
- */
-
- /*
- * s3.c - support routines for S3 86C911 based cards
- */
-
- #include "vdev.h"
- #include "video.h"
- #include "v86mode.h"
- #include "vesabios.h"
- #include "svga.h"
- #include "ibm8514.h"
-
- /*
- * NOTE: the S3 86C911 is a single chip VGA / SVGA / 8514
- * While it is not an exact 8514 clone (it doesn't have
- * a color compare register or fixed pattern registers
- * and it is programmed into the 8514 compatible modes
- * differently from an IBM 8514) it is completely compatible
- * for all of the basic drawing operations.
- *
- * modes 0x101 - 0x105 are VESA compatible SVGA modes
- * modes 0x201 - 0x205 are 8514 compatible
- *
- * the only extended modes supported here are the 256 color
- * 8514 compatible modes
- */
-
- /*
- * table of video modes supported for S3 86C911
- */
- #define GRAPHICS (SVGA_MODE_SUPPORTED | SVGA_GRAPHICS_MODE)
- #define TEXT (SVGA_MODE_SUPPORTED | SVGA_TEXT_MODE)
-
- static struct svga_mode_info s3_modes[] =
- {
- { 640, 480, 24, 0x112, GRAPHICS },
- { 640, 480, 16, 0x111, GRAPHICS },
- { 640, 480, 15, 0x110, GRAPHICS },
- { 1024, 768, 8, 0x205, GRAPHICS },
- { 800, 600, 8, 0x203, GRAPHICS },
- { 640, 480, 8, 0x101, GRAPHICS },
- { 320, 200, 8, 0x13, GRAPHICS },
- { 132, 25, 0, 0x55, TEXT },
- { 80, 25, 0, 0x03, TEXT },
- { 0, 0, 0, 0, 0 }
- };
-
- /*
- * S3 i/o registers
- */
- static unsigned short s3_byte_regs[] =
- {
- DAC_MASK,
- DAC_R_INDEX,
- DAC_W_INDEX,
- DAC_DATA,
- 0
- };
-
- static unsigned short s3_word_regs[] =
- {
- DISP_STAT,
- H_TOTAL,
- H_DISP,
- H_SYNC_STRT,
- H_SYNC_WID,
- V_TOTAL,
- V_DISP,
- V_SYNC_STRT,
- V_SYNV_WID,
- DISP_CNTL,
- ADVFUNC_CNTL,
- SUBSYS_STAT,
- SUBSYS_CNTL,
- ROM_PAGE_SEL,
- CUR_Y,
- CUR_X,
- DESTY_AXSTP,
- DESTX_DIASTP,
- ERR_TERM,
- MAJ_AXIS_PCNT,
- GP_STAT,
- CMD,
- SHORT_STROKE,
- BKGD_COLOR,
- FRGD_COLOR,
- WRT_MASK,
- RD_MASK,
- COLOR_CMP,
- BKGD_MIX,
- FRGD_MIX,
- MULTIFUNC_CNTL,
- PIX_TRANS
- };
-
- static void s3_reset();
- static int s3_setmode();
- static void s3_clear();
- static void s3_bank_switch();
-
- static int s3_initial_mode = -1;
- static int s3_current_bank = -1;
-
- extern struct svga_mode_info *SVGAModeInfo;
- extern struct svga_mode_info *SVGAModeTable;
-
- s3_io_enable()
- {
- unsigned short *ioaddr;
- /*
- * enable the additional i/o addresses
- */
- for (ioaddr = s3_byte_regs; *ioaddr != 0; ioaddr++)
- V86IOEnable(*ioaddr, 1);
-
- for (ioaddr = s3_word_regs; *ioaddr != 0; ioaddr++)
- V86IOEnable(*ioaddr, 2);
- }
-
- /*ARGSUSED*/
- int
- s3_init(
- char *name,
- struct vdev *v
- )
- {
- struct svga_mode_info *s;
-
- s3_io_enable();
- /*
- * set up additional mode information
- */
- for (s = s3_modes; s->attributes != 0; s++)
- {
- if (s->bios_mode >= 0x100)
- {
- s->scanline_length = (s->depth > 8) ? 2048 : 1024;
- if (s->depth == 24)
- {
- s->red_bits = 8;
- s->green_bits = 8;
- s->blue_bits = 8;
- s->red_shift = 16;
- s->green_shift = 8;
- s->blue_shift = 0;
- }
- }
- }
- svga_setup(v, s3_modes, s3_bank_switch);
-
- v->v_name = VESAVendorData();
- v->v_reset = s3_reset;
- v->v_setmode = s3_setmode;
- #if 0
- v->v_clear = s3_clear;
- #endif
-
- s3_initial_mode = VBiosGetMode();
-
- return 0;
- }
-
- int
- s3_probe()
- {
- int id;
- outw(0x3d4, 0x4838); /* unlock S3 special registers */
- outb(0x3d4, 0x30); /* select chip id register */
- id = inb(0x3d5); /* read chip id */
- outw(0x3d4, 0x0038); /* lock S3 special registers */
- return (id == 0x81 || id == 0x82);
- }
-
- /*
- * reset86c911() - reset the S3 graphics processor
- */
- static void
- reset_86c911()
- {
- outw(0x3d4, 0xa039); /* unlock system control registers */
- outb(0x3d4, 0x40); /* select system configuration register */
- outb(0x3d5, inb(0x3d5)|1); /* enable enhanced 8514 mode registers */
- outw(0x3d4, 0x0039); /* lock system control registers */
- outw(SUBSYS_CNTL, 0x9000); /* disable and reset */
- outw(SUBSYS_CNTL, 0x5000); /* enable */
- }
-
- static void
- s3_reset()
- {
- reset_86c911();
- if (s3_initial_mode != -1)
- VBiosSetMode(s3_initial_mode);
- }
-
- /*
- * s3_setmode()
- */
- static int
- s3_setmode(
- int i
- )
- {
- extern unsigned R16Shift, G16Shift, B16Shift;
- extern unsigned R16Bits, G16Bits, B16Bits;
- extern unsigned R24Shift, G24Shift, B24Shift;
- extern unsigned R24Bits, G24Bits, B24Bits;
- struct svga_mode_info *s;
-
- s = &s3_modes[i];
-
- reset_86c911();
-
- s3_current_bank = -1;
-
- if (s->bios_mode < 0x100)
- {
- VBiosSetMode(s->bios_mode | 0x80);
- if ((VBiosGetMode() & 0x7f) != s->bios_mode)
- return -1;
- }
- else
- {
- if (VESABiosSetMode(s->bios_mode) != 0)
- return -1;
- }
-
- if (s->attributes & SVGA_TEXT_MODE)
- {
- VBiosDisableBlink();
- VBiosSetCursorPosition(s->width, s->height);
- }
-
- /*
- * make sure start address is 0
- */
- outw(0x3d4, 0x000c);
- outw(0x3d4, 0x000d);
-
- if (s->attributes & SVGA_GRAPHICS_MODE)
- {
- switch (s->depth)
- {
- case 15:
- case 16:
- case 24:
- RGB32Shift[0] = s->red_shift;
- RGB32Shift[1] = s->green_shift;
- RGB32Shift[2] = s->blue_shift;
- RGB32Bits[0] = s->red_bits;
- RGB32Bits[1] = s->green_bits;
- RGB32Bits[2] = s->blue_bits;
- break;
-
- default:
- break;
- }
- }
- SVGAModeInfo = s;
- return 0;
- }
-
- /*
- * s3_clear()
- */
- static void
- s3_clear(
- int bg
- )
- {
- struct svga_mode_info *s = SVGAModeInfo;
-
- if (s->bios_mode < 0x100)
- {
- int n;
-
- n = s->scanline_length * s->height;
-
- if (s->attributes & SVGA_TEXT_MODE) /* text mode */
- memset(0xb8000, bg | (bg << 4), n);
- else
- memset(0xa0000, bg, n);
- return;
- }
-
- WAIT_QUEUE(4);
-
- outw(WRT_MASK, 0x00ff);
- outw(MULTIFUNC_CNTL, PIX_CNTL | 0);
- outw(BKGD_COLOR, bg);
- outw(FRGD_MIX, 0x0007);
-
- WAIT_QUEUE(5);
-
- outw(CUR_X, 0x0000);
- outw(CUR_Y, 0x0000);
- outw(MAJ_AXIS_PCNT, s->scanline_length - 1);
- outw(MULTIFUNC_CNTL, MIN_AXIS_PCNT | (s->height - 1));
-
- outw(CMD, 0x43b3); /* command */
- }
-
- static void
- s3_bank_switch(
- int bank
- )
- {
- if (bank != s3_current_bank)
- VESABiosBankSwitch(bank);
- s3_current_bank = bank;
- }
-